package com.le.tester.imooc.masterJUC.lock.reentrantlock;

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 描述：
 */
public class Upgrading {


    //AtomicInteger;

    //多读，要控制成唯一写，一写多读
    private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock(false);
    //读
    private static ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
    //写
    private static ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();

    public static void main(String[] args) {
        System.out.println("降级是可以的");
        //如果你不自己创建一个线程的话，那么就会默认的使用main的这个线程
        //Upgrading.writeDowngrading();
        new Thread(Upgrading::writeDowngrading, "thread1").start();

        //升级是不可以的,需要读锁全部执行完毕，不要一直等待释放
        System.out.println("升级是不可以的");
        new Thread(Upgrading::readUpGrading, "thread2").start();
    }


    private static void readUpGrading() {
        readLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 得到了读锁，正在读取中");
            Thread.sleep(1000);
            System.out.println("带来了阻塞吗？");
            //读变成了写，属于升级了
            System.out.println("锁住了之前：" + writeLock.getHoldCount());
            writeLock.lock();
            System.out.println("锁住了之后:" + writeLock.getHoldCount());
            System.out.println(Thread.currentThread().getName() + " 获取到了写锁");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            writeLock.unlock();
            System.out.println(Thread.currentThread().getName() + " 释放了读锁");
            readLock.unlock();
        }
    }

    private static void writeDowngrading() {
        writeLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 得到了写锁，正在写入中");
            Thread.sleep(1000);
            //写锁变成了读锁，变成了降级
            readLock.lock();
            System.out.println(Thread.currentThread().getName() + " 在不释放写锁的情况下，获取到了读锁，成功降级");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            readLock.unlock();
            System.out.println(Thread.currentThread().getName() + " 释放了写锁");
            writeLock.unlock();
        }
    }
}
